#ifndef __MINIUTIL_MULTINET_MHTTPCLIENT_H__
#define __MINIUTIL_MULTINET_MHTTPCLIENT_H__

#include <string>
#include <map>
#include "miniutil/fifobuf.h"
#include "miniutil/socketmultiplex.h"
#include "miniutil/url.h"

namespace miniutil { namespace multinet {

		class httpformdata
		{
		public:
			std::string type;
			std::string name;
			std::string value;
		};
/*
usage sample:
	while(true)
	{
			hcli.working();
			int ret = hcli.get_status();
			if(ret == httpclient::STUS_FIN || ret == httpclient::STUS_FAIL)
				return 1;
			switch(ret)
			{
			case httpclient::STUS_CONNETING:
				stus = "connecting...";
				break;
			case httpclient::STUS_CONNECTED:
				stus = "connected...";
				break;
			case httpclient::STUS_REQDONE:
				stus = "req sent...";
				break;
			case httpclient::STUS_RESP_HEADER:
				stus = "have receive header...";
				ret = hcli.get_resp_content(buf, sizeof(buf));
				if(ret > 0)
				{
					haveread += ret;
					//std::cout<<checkurl<<" reading "<<haveread<<std::endl;
				}
				break;
			case httpclient::STUS_FIN:
				stus = "receive content finish";
				std::cout<<checkurl<<" total read "<<haveread<<std::endl;
				break;
			case httpclient::STUS_FAIL:
				stus = "connect fail";
				break;
			}
	}		
*/
		class httpclient
		{
		public:
			const static int STUS_NONE = 0;
			const static int STUS_CONNETING = 1;
			const static int STUS_CONNECTED = 2;
			const static int STUS_REQDONE = 3;
			const static int STUS_RESP_HEADER = 4;
			const static int STUS_FIN = 5;  //body received
			const static int STUS_FAIL = 6;
			const static int STUS_TIMEOUT = 7;

		public:
			httpclient(SocketMulplexService*);
			~httpclient();
			
			int do_GET(std::string urlstr, std::string method = std::string("GET"), 
				int from = -1, int to = -1,
				int timeoutms = 10000);
			int do_POSTFORM_URL(std::string urlstr, std::vector<httpformdata> &vformdata, int timeoutms = 10000);
			int do_POSTFORM_MULPART(std::string urlstr, std::vector<httpformdata> &vformdata, int timeoutms = 10000);
			//void do_post();
		private:			
			//req para
			std::string urlstr;
			std::string method;
			int mbytefrom, mbyteto;
			std::vector<httpformdata> vformdata;
			int timeoutms;
					
			miniutil::url httpURL;
			SocketMulplexService *mpss;
			std::string mreqheader;
			std::string mrespheader;
	    
			SOCKET httpsoc;
			int mstatus;
		public:
			int working();
			std::string get_req_url(){return urlstr;}
			int get_status(){return mstatus;}
			int get_resp_code(){return mrespcode;}
			std::string get_resp_content_type(){return mresptype;}
			int get_resp_len(){return mresplen;}
			
			inline string getRespHeader(char * key )
			{
				miniutil::auto_lock k(&mclientmtx);
				if(respheaders.find(string(key)) != respheaders.end())
					return respheaders[string(key)];
				return string();
			}
			inline string getRespHeader( string & key )
			{
				miniutil::auto_lock k(&mclientmtx);
				if(respheaders.find(key) != respheaders.end())
					return respheaders[key];
				return string();
			}
			inline void setReqHeader(char *key, char * value)
			{
				miniutil::auto_lock k(&mclientmtx);
				reqheaders[string(key)] = value;
			}
			inline void setReqHeader( string &key, string& value )
			{
				miniutil::auto_lock k(&mclientmtx);
				reqheaders[key] = value;
			}
			
			int get_resp_content(char*, int);
			//-----------------
		public://helper function
			bool is_resp_ok()
			{
				return (mrespcode>=200 && mrespcode < 300);
			}
			bool is_resp_redirect()
			{
				return (mrespcode>=300 && mrespcode < 400);
			}
			bool is_resp_fail()
			{
				return (mrespcode>=400 || mrespcode < 200);
			}
		private:	
			miniutil::data::fifobuf recvbuf;
			map<string, string> reqheaders;
			map<string, string> respheaders;
			char headerbuf[8192];
			int havereadheader;
			
			void working_status_none();
			void working_status_connecting();
			void working_status_connected();
			void working_status_reqdone();
			void working_status_headerdone();
			
			int analyze_header();
			int mrespcode;
			std::string mresptype;
			int mresplen;
			
			int mcontenthaverecv;

			miniutil::mutex mclientmtx;

			miniutil::m_uint32_t mltmstactive;	//last active time..
		};

/*
class mhttpclient_service:public miniutil::thread::runnable
{
	
	mhttpclient();
	~mhttpclient();
	void start();
	void stop();
	
	void request_get(std::string url);
	void request_post();
	void reponse(std::string url);
	void close(std::string url);
	
	void run();
	
	std::map<std::string, httpstatus> mallhttps;

};
*/
} }

#endif
